#include "stdafx.h"
#include "CtpMarketDataLink.h"
#include "config.h"
#include "LogFile.h"
#include <sstream>


CtpMarketDataLink::CtpMarketDataLink(const string &name, CThostFtdcMdApi *api)
	: CtpLinkBase(), MarketDataLink() {
	mMdApi = api;
	mName = name;
	Config *cfg = Config::getInstance();
	mDisplayMarketData = (cfg->getValue("DisplayMarketData", 0) == 1);
	mRequestID = 0;
}


CtpMarketDataLink::~CtpMarketDataLink() {
}

void CtpMarketDataLink::Connect() {
	mMdApi->Init();
}

void CtpMarketDataLink::Disconnect() {
	// no need to logout for market data
}

void CtpMarketDataLink::OnRspUserLogout(CThostFtdcUserLogoutField *userLogout, 
	CThostFtdcRspInfoField *rspInfo, int requestID, bool isLast) {
	stringstream ss;
	if( RspError(rspInfo, "OnRspUserLogout", ss) ) {
		LogFile::PrintLine(ss.str().c_str());
		mDialog->addMessage(ss.str().c_str());
		return;
	}

	ss << "market data session logged out succesfully";
	LogFile::PrintLine("Market data session logged out succesfully");
	mDialog->addMessage(ss.str().c_str());
}

void CtpMarketDataLink::OnFrontConnected() {
	mDialog->addMessage("Market data link front end connected, sending login info now");
	CThostFtdcReqUserLoginField field;
	setLoginField(&field);
	mMdApi->ReqUserLogin(&field, 0);
}

void CtpMarketDataLink::OnFrontDisconnected() {
	mDialog->addMessage("Market data link front end disconnected");
}

void CtpMarketDataLink::OnRspUserLogin(CThostFtdcRspUserLoginField *rspLogin,
	CThostFtdcRspInfoField *rspInfo, int reqID, bool isLast) {
	std::stringstream ss;
	if( rspInfo->ErrorID != 0 ) {
		ss	<< "Market data login failed. ErrorCode=" << rspInfo->ErrorID 
			<< "ErrorMsg=" << rspInfo->ErrorMsg
			<< "RequestID=" << reqID
			<< "IsLast=" << isLast;
		mDialog->addMessage(ss.str().c_str());
	} else {
		int len = mInstrumentsVector.size();
		int status = -1;
		if(len > 0)
			status = mMdApi->SubscribeMarketData (mInstrumentsArray, len);

		ss << "Market data login succesful. Start to subscribe market data for "
			<< len << " instruments. Status=" << status;
		mDialog->addMessage(ss.str().c_str());
		for(int i=0; i<len; i++)
			mDialog->addMessage(string(mInstrumentsArray[i]));
	}
}

void CtpMarketDataLink::OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *field) {
	string instrID = string(field->InstrumentID);
	CommInstrument * instr = mInstrList->GetInstrumentByID(instrID);

	std::stringstream ss;

	if(instr == 0) {
		ss << "Cannot find instrument for the received market data " << instrID;
		mDialog->addMessage(ss.str().c_str());
		return;
	}

	ZAdaptorMarketDataBestLevelMessage *msg = &instr->MarketDataBestLevelSnapshot;
	msg->zSymbolField.zVal = instr->InstrumentID.c_str();
	msg->zBestBidPxField.zVal = field->BidPrice1;
	msg->zBestBidSzField.zVal = field->BidVolume1;
	msg->zBestAskPxField.zVal = field->AskPrice1;
	msg->zBestAskSzField.zVal = field->AskVolume1;
	msg->zTimestampField.zVal = field->UpdateTime;

	instr->HasMarketDataBestLevelSnapshot = true;

	if(field->Volume > 0) {
		ZAdaptorMarketDataTradeMessage *trdMsg = &instr->MarketTradeSnapshot;
		trdMsg->zSymbolField.zVal = instr->InstrumentID.c_str();
		trdMsg->zLastPxField.zVal = field->LastPrice;
		trdMsg->zTimestampField.zVal = field->UpdateTime;
		if(instr->HasMarketDataTradeSnapshot) {
			trdMsg->zLastSzField.zVal = field->Volume - trdMsg->zVolumeField.zVal;
			trdMsg->zVolumeField.zVal = field->Volume;
			if(instr->HasMarketDataBestLevelSnapshot)
				instr->CanPublish = true;
		} else {
			trdMsg->zVolumeField.zVal = field->Volume;
			instr->HasMarketDataTradeSnapshot = true;
		}
	}

	if(instr->CanPublish) {
		instr->PubMarketDataBestLevelSnapshot();
		instr->PubMarketTradeSnapshot();
	}

	if(mDisplayMarketData) {
		ss	<< field->InstrumentID << " " 
			<< field->BidVolume1 << " "
			<< field->BidPrice1 << " "
			<< field->AskPrice1 << " "
			<< field->AskVolume1 << " "
			<< field->Volume;

		mDialog->addMessage(ss.str().c_str());
	}
}

void CtpMarketDataLink::OnRspError(CThostFtdcRspInfoField *rspInfo, int requestID, bool isLast) {
	std::stringstream ss;
	ss << "OnRspError(Market Data): ErrorCode=" << rspInfo->ErrorID << " ErrorMsg=" << rspInfo->ErrorMsg;
	mDialog->addMessage(ss.str().c_str());
}